#include "S5Server.h"
#include <KDebug.h>
#include <KSockAddress.h>
#include <KTimerQueue.h>
#include "S5ActionClient.h"
#include "S5ActionServer.h"

S5Server::S5Server(LONG max, u_short port) :
    m_context(NULL),
    m_extra(max >> 10),
    m_max(max),
    m_port(port)
{
    if (m_extra < 5) {
        m_extra = 5;
    }
    m_queue = new KTimerQueue;
}

S5Server::~S5Server()
{
    delete m_queue;
}

LONG S5Server::clients() const
{
    return m_context ? m_context->clients() : 0;
}

LONG S5Server::totalClients() const
{
    return m_context ? m_context->totalClients() : 0;
}

LONG S5Server::extraAccepts() const
{
    return m_context ? m_context->extraAccepts() : m_extra;
}

void S5Server::setExtraAccepts(LONG extra)
{
    if (extra >= 0) {
        m_extra = extra;
    }
}

bool S5Server::isRunning() const
{
    return m_context && (m_context->clients() > 0 || m_context->extraAccepts() >= 0);
}

bool S5Server::allow(const KIpAddress &address) const
{
    return true;
}

bool S5Server::requireAuthentication() const
{
    return false;
}

bool S5Server::verify(const std::string &username, const std::string &password) const
{
    return false;
}

bool S5Server::sendAck(KSocket *sock, const void *data, size_t length)
{
    struct Ackey : KKey {};
    return send(sock, data, length, new Ackey);
}

void S5Server::onAborted(S5ActionClient *client)
{
    KDebugMsg("Client %s(%s:%d) aborted: %d",
        client->username().c_str(),
        client->address().ip(),
        client->address().port(),
        client->state());
}

void S5Server::onStarted()
{
    if (m_max > 0) {
        m_context = new S5ActionServer(m_max, m_extra);
        if (KSocket *acceptor = addAcceptor(KIpAddress(m_port), m_context, -1, true, m_extra)) {
            ensureAlive(acceptor);
        } else {
            m_context = NULL;
        }
    }
}

void S5Server::onStopped()
{
    m_context = NULL;
}